import traceback
from datetime import timedelta

import numpy as np
import pandas as pd

from 资金费率监控.utils.commons import sleep_until_run_time
from 资金费率监控.utils.dingding import *


def main():
    # 获取U本位合约和币本位合约资金费率信息并发送钉钉
    fetch_future_funding_rate()
    # 整点sleep
    sleep_until_run_time(time_interval)


# 监控U本位永续合约资金费率
def fetch_future_funding_rate():
    # 最新标记价格和资金费率
    # GET /fapi/v1/premiumIndex
    usdt_df = pd.DataFrame(exchange.fapiPublicGetPremiumIndex())
    usdt_symbol_precision_info = np.load('data/usdt_symbol_precision_info.npy', allow_pickle=True).item()
    dealing_future_funding_rate_df(usdt_df, usdt_symbol_precision_info)  # 处理U本位永续合约数据

    time.sleep(1)  # 防止频繁抓取数据
    # 最新现货指数价格和Mark Price
    # GET /dapi/v1/premiumIndex
    _coin_df = pd.DataFrame(exchange.dapiPublicGetPremiumIndex())
    coin_df = _coin_df[_coin_df['symbol'].str.endswith('PERP')].sort_values('symbol')  # 过滤交割合约
    coin_symbol_precision_info = np.load('data/coin_symbol_precision_info.npy', allow_pickle=True).item()
    dealing_future_funding_rate_df(coin_df, coin_symbol_precision_info)


# 处理资金费率有关的数据
def dealing_future_funding_rate_df(df, symbol_precision_info):
    def get_usdt_symbol_precision(symbol):
        price_precision, quantity_precision = symbol_precision_info[symbol]
        return price_precision

    df = df[abs(df['lastFundingRate'].astype(float)) > funding_rate_threshold]  # 最低资金费率限制
    df = df[df['markPrice'].astype(float) > price_threshold]  # 最低价格限制
    if df.empty is False:
        # 先转成float去除误差，再将时间戳转化为北京时间
        df['nextFundingTime_GMT8'] = pd.to_datetime(df['nextFundingTime'].astype(float), unit='ms') + timedelta(hours=8)
        df['usdt_symbol_precision'] = df['symbol'].apply(get_usdt_symbol_precision).astype(int)
        # 'markPrice'按照usdt_symbol_precision_info中的精度信息保留小数
        df['markPrice'] = df.apply(lambda row: round(float(row['markPrice']), int(row['usdt_symbol_precision'])),
                                   axis=1)
        df['lastFundingRate'] = df['lastFundingRate'].astype(float).apply(lambda x: '%.2f%%' % (x * 100))
        df = df[['nextFundingTime_GMT8', 'symbol', 'markPrice', 'lastFundingRate']]

        df.sort_values('symbol', inplace=True)
        df.reset_index(drop=True, inplace=True)
        # 结果发送钉钉
        send_dingding_msg_for_funding_rate(df)


if __name__ == '__main__':
    send_dingding_msg('资金费率监控程序：\n')
    while True:
        try:
            main()
        except Exception as e:
            msg = '系统出错，10s之后重新运行，出错原因：' + str(e)
            print(msg)
            print(traceback.format_exc())
            send_dingding_msg(msg)
        time.sleep(10)
